Advertisement
  1. Code
  2. PHP

Tu guía integral para los comandos de Laravel

Scroll to top
Read Time: 16 min

() translation by (you can also view the original English article)

En esta época, es bastante normal que un desarrollador tenga conocimiento de las consolas y de cómo emitir comandos básicos. Pero, ¿y si pudieras codificar tus propios comandos personalizados para mejorar tu flujo de trabajo? Si tenemos en cuenta a Laravel 3, es posible que recuerdes que ofrecía tareas. Las tareas eran extremadamente útiles, pero aún así se quedaron cortas en operaciones más complejas. Afortunadamente, Laravel 4 incluye un Artisan reforzado que hará tu vida como desarrollador mucho más fácil.


¿Qué es Artisan?

Artisan es la herramienta de línea de comandos que se lanzó en Laravel 3.

Si no estás familiarizado con Laravel, es posible que no conozcas Artisan. Artisan es la herramienta de línea de comandos que se lanzó en Laravel 3. Si has usado otros frameworks, puedes comparar Artisan con Oil en FuelPHP, ZFTool en Zend o la consola en Symfony 2.

Artisan ofrece muchos comandos útiles que pueden ayudarte a realizar diversas tareas, como generar migraciones o publicar los recursos de un paquete. Además de los comandos integrados, puedes ampliar Artisan con tus propios comandos.


Fundamentos de Artisan

Aquí es donde Artisan saca su poder.

En Laravel 3, Artisan fue escrito desde cero por Taylor Otwell (creador de Laravel), por lo que era bastante básico (aunque aún impresionante). Ya que Laravel 4 está basado en Composer, puede usar paquetes existentes desarrollados por otros desarrolladores brillantes. Como resultado, Laravel 4 ahora depende de numerosos paquetes del framework Symfony. Uno de estos paquetes es el excelente componente de consola.

Si revisamos la fuente de la aplicación Artisan en Illuminate\Console\Application, podemos ver que la clase, en sí misma, extiende Symfony\Component\Console\Application. Aquí es donde Artisan saca su poder. Aunque Artisan hace uso del componente Consola de Symfony, a muchos de los métodos comunes se les han dado alias de Laravel más fluidos. Así que no te preocupes, ¡todavía sentirás que estás desarrollando con Laravel!


Preguntas comunes

Por lo general, surgen dos preguntas cuando se intenta desarrollar un nuevo comando.

P ¿Dónde debo poner los comandos?

Al instalar una copia de Laravel, encontrarás un directorio predefinido en app/commands. Este directorio también se encuentra en el classmap de tu composer.json de forma predeterminada. Esto significa que, una vez que hayas creado un comando, deberás ejecutar composer dump-autoload para generar un archivo de carga automática actualizado. Si no lo haces, recibirás errores, quejándose de que no se puede encontrar tu comando.

Si estás desarrollando un paquete, deberás crear un directorio dentro de tu directorio src/<vendor>/<package> para contener tus comandos. En todo el código base de Laravel 4, este directorio se llama Console. Recuerda asegurarte de que el directorio se cargue automáticamente en tus paquetes composer.json.

P ¿Cómo debo nombrar los comandos?

En todo el código base de Laravel 4, todos los comandos tienen el sufijo Command y reciben el nombre de la tarea que realizan. Supongamos, por ejemplo, que tienes un comando que borra tu memoria caché. Puedes nombrar este comando, CacheClearCommand.


Conceptos básicos de un comando

Un comando debe realizar una sola tarea. Durante el resto de este artículo, desarrollaremos un comando de generador de usuarios. Repasemos los conceptos básicos de un comando.

1
    // app/commands/UserGeneratorCommand.php <?php use Illuminate\Console\Command; class UserGeneratorCommand extends Command { /** * The console command name. * * @var string */ protected $name = 'user:generate'; /** * The console command description. * * @var string */ protected $description = "Generate a new user"; /** * Execute the console command. * * @return void */ public function fire() { $this->line('Welcome to the user generator.'); } }
2
  

¡Laravel puede generar este código reutilizable para ti! Simplemente ejecuta:

1
    $ php artisan command:make UserGeneratorCommand
2
  

Esto creará un comando esqueleto para que lo modifiques, sin embargo, para los propósitos de este tutorial, pasaremos por el proceso de construcción de un comando desde cero, para que podamos aprender cada parte del proceso.

Nombre del comando

Todos los comandos deben proporcionar un nombre. Este nombre se utiliza para ejecutar el comando desde la consola y debe describir la tarea que realiza el comando. Si bien no existe una convención sobre el nombre de tu comando, puedes tener en cuenta uno de los siguientes: namespace:group/commandnamespace:command, o solo command.

Descripción del comando

Todos los comandos deben proporcionar una descripción. La descripción se utiliza al recuperar una lista de comandos disponibles de Artisan y al ver los documentos de ayuda para un comando. Las descripciones deben describir brevemente la tarea que realiza el comando.

Si abriéramos nuestra consola y obtuviéramos una lista de comandos disponibles, aún no podremos ver nuestro comando en la lista.

1
    $ php artisan list Laravel Framework version 4.0.0 Usage: [options] command [arguments] Options: --help -h Display this help message. --quiet -q Do not output any message. --verbose -v Increase verbosity of messages. --version -V Display this application version. --ansi Force ANSI output. --no-ansi Disable ANSI output. --no-interaction -n Do not ask any interactive question. --env The environment the command should run under. Available commands: help Displays help for a command list Lists commands migrate Run the database migrations serve Serve the application on the PHP development server tinker Interact with your application workbench Create a new package workbench asset asset:publish Publish a package's assets to the public directory auth auth:reminders Create a migration for the password reminders table command command:make Create a new Artisan command config config:publish Publish a package's configuration to the application controller controller:make Create a new resourceful controller db db:seed Seed the database with records key key:generate Set the application key migrate migrate:install Create the migration repository migrate:make Create a new migration file migrate:refresh Reset and re-run all migrations migrate:reset Rollback all database migrations migrate:rollback Rollback the last database migration queue queue:listen Listen to a given queue queue:work Process the next job on a queue session session:table Create a migration for the session database table
2
  

Para registrar nuestro nuevo comando, abre app/start/artisan.php y lee rápidamente el bloque de comentarios predeterminado que está ahí. Cuando ejecutamos Artisan desde la consola, se incluye este archivo; lo usaremos para arrancar nuestros comandos. En este archivo, tenemos acceso a una variable $artisan que se declaró antes de incluir el archivo. ¿Recuerdas la clase de aplicación Artisan que vimos anteriormente? ¿El que extendió el componente de la Consola Symfony? Bueno, $artisan es una instancia de esa clase.

Agreguemos nuestro comando para que esté disponible en la consola.

1
    $artisan->add(new UserGeneratorCommand);
2
  

O, si prefieres la sintaxis estática:

1
    Artisan::add(new UserGeneratorCommand);
2
  

El método add acepta una instancia de comando. Una vez agregado nuestro comando, podemos acceder a él desde la consola.

1
    $ php artisan user:generate Welcome to the user generator.
2
  

El comando también debe aparecer en los comandos disponibles, así como en la información de ayuda.

1
    $ php artisan list
2
  
1
    $ php artisan user:generate --help Usage: user:generate Options: --help (-h) Display this help message. --quiet (-q) Do not output any message. --verbose (-v) Increase verbosity of messages. --version (-V) Display this application version. --ansi Force ANSI output. --no-ansi Disable ANSI output. --no-interaction (-n) Do not ask any interactive question. --env The environment the command should run under.
2
  

Si recibes algún error, asegúrate de ejecutar composer dump-autoload desde la raíz de tu aplicación, después de crear el comando.


Salida de color

La salida de texto en color a la consola es muy fácil en Artisan. Hay cuatro métodos de ayuda diferentes para hacer eco de la salida ANSI de color.

1
    $this->info("This is some information."); $this->comment("This is a comment."); $this->question("This is a question."); $this->error("This is an error.");
2
  

Opciones y argumentos

Una nueva característica interesante de Artisan es la capacidad de proporcionar un comando con opciones y argumentos.

Argumentos

Los argumentos son cadenas que envías a un comando. Deben asignarse a un comando en el orden en que se definen. Ten en cuenta el siguiente comando:

1
    $ php artisan user:generate [name] [email]
2
  

El argumento name debe especificarse antes del argumento email.

Los argumentos se pueden definir como opcionales.

Opciones

Las opciones siempre son opcionales y tienen como prefijo dos guiones cuando se proporcionan.

1
    $ php artisan user:generate --admin
2
  

Además de usarse como conmutadores booleanos, se puede configurar una opción para aceptar un valor o una matriz de valores.

1
    $ php artisan user:generate --name=Jason $ php artisan user:generate --role=user --role=editor
2
  

Definición de opciones y argumentos

Antes de definir nuestras opciones y argumentos, es mejor importar las clases de Symfony requeridas (son largas y sería complicado escribirlas todo el tiempo). Las dos clases que necesitamos son Symfony\Component\Console\Input\InputOption y Symfony\Component\Console\Input\InputArgument.

Por encima de nuestra declaración de clase, importaremos ambas clases.

1
    // app/commands/UserGenerateCommand.php <?php use Illuminate\Console\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; class UserGeneratorCommand extends Command { /** * The console command name. * * @var string */ protected $name = 'user:generate'; /** * The console command description. * * @var string */ protected $description = "Generate a new user"; /** * Execute the console command. * * @return void */ public function fire() { $this->line('Welcome to the user generator.'); } }
2
  

Para definir las opciones y argumentos, debes crear dos nuevos métodos: getArguments y getOptions. Ambos métodos devuelven una matriz de argumentos u opciones. Hagamos que nuestro comando acepte un argumento name y una opción age.

1
    // app/commands/UserGenerateCommand.php <?php use Illuminate\Console\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; class UserGeneratorCommand extends Command { /** * The console command name. * * @var string */ protected $name = 'user:generate'; /** * The console command description. * * @var string */ protected $description = "Generate a new user"; /** * Execute the console command. * * @return void */ public function fire() { $this->line('Welcome to the user generator.'); // Get the name arguments and the age option from the input instance. $name = $this->argument('name'); $age = $this->option('age'); $this->line("{$name} is {$age} years old."); } /** * Get the console command arguments. * * @return array */ protected function getArguments() { return array( array('name', InputArgument::REQUIRED, 'Name of the new user'), ); } /** * Get the console command options. * * @return array */ protected function getOptions() { return array( array('age', null, InputOption::VALUE_REQUIRED, 'Age of the new user') ); } }

2
  

Recuerda: Laravel puede generar todo este código reutilizable por ti. Simplemente lo estamos haciendo manualmente con el propósito de revisar cada línea de la clase.

Ahora, podemos proporcionar un argumento name y una opción age desde nuestra consola.

1
    $ php artisan user:generate Jason --age=22 Jason is 22 years old.
2
  

Tanto los argumentos como las opciones se definen como matrices multidimensionales. Revisemos más de cerca a las definiciones de cada uno de ellos.

Definiciones de argumentos

La definición de matriz para un argumento acepta cuatro claves, y solo se requiere la primera (el nombre de los argumentos). La segunda clave es el modo de argumentos y debe ser InputArgument::OPTIONAL o InputArgument::REQUIRED. La tercera es la descripción, y la cuarta clave es un valor predeterminado, si el modo se configura en InputArgument::OPTIONAL.

Este es un argumento que usa todas las claves de la matriz.

1
    array('name', InputArgument::OPTIONAL, 'Name of the new user', 'Jason')
2
  

Definiciones de opciones

La definición de matriz para una opción acepta cinco claves y solo se requiere la primera (el nombre de la opción). La segunda clave es un atajo para la opción (-a por ejemplo). La tercera es el modo de opciones y puede ser uno de los siguientes valores: InputOption::VALUE_NONE, InputOption::VALUE_REQUIRED, InputOption::VALUE_OPTIONAL o InputOption::VALUE_IS_ARRAY. La cuarta clave es la descripción de las opciones y la quinta clave es un valor predeterminado, si el modo no es InputOption::VALUE_NONE o InputOption::VALUE_REQUIRED.

Esta es una opción, usando todas las claves de la matriz.

1
    array('age', 'a', InputOption::VALUE_OPTIONAL, 'Age of the new user', 22)
2
  

También puedes combinar el modo InputOption::VALUE_IS_ARRAY con InputOption::VALUE_REQUIRED o InputOption::VALUE_OPTIONAL.

1
    array('role', 'r', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Roles of the new user', 'user')
2
  

Confirmaciones y preguntas

Otra característica nueva y emocionante de Artisan es su capacidad para solicitar confirmación, o incluso hacerle una pregunta al usuario. Esto hace que el desarrollo de comandos interactivos sea lo más sencillo posible.

Confirmaciones

Usando confirm, podemos hacerle una pregunta a un usuario, y hacer que confirme con un "sí" o "no". Confirmemos que el usuario ingresó su edad correctamente.

1
    // app/commands/UserGenerateCommand.php <?php use Illuminate\Console\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; class UserGeneratorCommand extends Command { /** * The console command name. * * @var string */ protected $name = 'user:generate'; /** * The console command description. * * @var string */ protected $description = "Generate a new user"; /** * Execute the console command. * * @return void */ public function fire() { $this->line('Welcome to the user generator.'); // Get the name arguments and the age option from the input instance. $name = $this->argument('name'); $age = $this->option('age'); if ( ! $this->confirm("Are you really {$age} years old? [yes|no]", true)) { $this->comment('Then why did you say you were!?'); return; } $this->comment("{$name} is {$age} years old."); } /** * Get the console command arguments. * * @return array */ protected function getArguments() { return array( array('name', InputArgument::REQUIRED, 'Name of the new user'), ); } /** * Get the console command options. * * @return array */ protected function getOptions() { return array( array('age', null, InputOption::VALUE_REQUIRED, 'Age of the new user', null) ); } }

2
  

El primer parámetro es la pregunta que te gustaría hacer, y el segundo es el valor predeterminado, si un usuario presiona Enter sin escribir nada.

Preguntas

Usando ask, podemos hacerle una pregunta a un usuario y esperar una respuesta de ellos. En lugar de eliminar nuestro comando si el usuario especifica que ingresó su edad incorrectamente, vamos a pedirle que la ingrese nuevamente.

1
    // app/commands/UserGenerateCommand.php <?php use Illuminate\Console\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; class UserGeneratorCommand extends Command { /** * The console command name. * * @var string */ protected $name = 'user:generate'; /** * The console command description. * * @var string */ protected $description = "Generate a new user"; /** * Execute the console command. * * @return void */ public function fire() { $this->line('Welcome to the user generator.'); // Get the name arguments and the age option from the input instance. $name = $this->argument('name'); $age = $this->option('age'); // Confirm the user entered their age correctly and if they haven't we'll // ask them to enter it again. if ( ! $this->confirm("Are you really {$age} years old? [yes|no]", true)) { $age = $this->ask('So how old are you then?'); } $this->comment("{$name} is {$age} years old."); } /** * Get the console command arguments. * * @return array */ protected function getArguments() { return array( array('name', InputArgument::REQUIRED, 'Name of the new user'), ); } /** * Get the console command options. * * @return array */ protected function getOptions() { return array( array('age', null, InputOption::VALUE_REQUIRED, 'Age of the new user', null) ); } }

2
  

Dependencias de comando

La inyección de dependencia es un paso importante para garantizar que tu código sea comprobable y esté preparado para el futuro. Llevemos nuestro comando un paso más allá inyectando una instancia de modelo, para que podamos generar el usuario. Comenzaremos creando una interfaz de usuario y un modelo de usuario.

1
    // app/models/UserInterface.php <?php interface UserInterface { }
2
  

Nuestra UserInterface no define realmente ninguna implementación de método, ya que esto solo es un ejemplo. Para una aplicación del mundo real, definirías los métodos que esperarías en tu modelo.

1
    // app/models/User.php <?php class User extends Eloquent implements UserInterface { /** * The database table used by the model. * * @var string */ protected $table = 'users'; }
2
  

Ya que tenemos nuestro modelo User implementando nuestra UserInterface, podemos continuar configurando nuestra dependencia en nuestro comando. Voy a agregar un poco más a nuestro comando generate e interactuar con el modelo User inyectado.

1
    // app/commands/UserGenerateCommand.php <?php use Illuminate\Console\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; class UserGeneratorCommand extends Command { /** * The console command name. * * @var string */ protected $name = 'user:generate'; /** * The console command description. * * @var string */ protected $description = "Generate a new user"; /** * User model instance. * * @var UserInterface */ protected $user; /** * Create a new UserGeneratorCommand instance. * * @param UserInterface $user * @return void */ public function __construct(UserInterface $user) { $this->user = $user; } /** * Execute the console command. * * @return void */ public function fire() { $this->line('Welcome to the user generator.'); // Get the name arguments and the age option from the input instance. $this->user->name = $this->argument('name'); $this->user->age = $this->option('age'); // Confirm the user entered their age correctly and if they haven't we'll // ask them to enter it again. We'll continue asking them until they are // sure they've entered the right age. $correctAge = false; while ( ! $correctAge) { if ( ! $this->confirm("Are you really {$this->user->age} years old? [yes|no]", true)) { $this->user->age = $this->ask('So how old are you then?'); } else { $correctAge = true; } } $this->user->framework = $this->ask('What is your favorite framework?', 'Laravel'); $this->user->website = $this->ask('What is your website address?'); // Save the user to the database. $this->user->save(); // Report that the user has been saved. $this->info("{$this->user->name} has been generated and saved."); } /** * Get the console command arguments. * * @return array */ protected function getArguments() { return array( array('name', InputArgument::REQUIRED, 'Name of the new user'), ); } /** * Get the console command options. * * @return array */ protected function getOptions() { return array( array('age', null, InputOption::VALUE_REQUIRED, 'Age of the new user', null) ); } }

2
  

Lo primero que debes notar es que el comando ahora tiene un constructor. Este constructor acepta un único parámetro e insinuamos el UserInterface, por lo que sabemos que la clase que obtenemos implementa los métodos definidos en la interfaz. Los constructores de comandos también deben llamar al constructor primario.

En el método fire del comando, asignamos directamente las propiedades en la instancia del modelo User. También estamos usando un bucle para continuar preguntándole al usuario si ingresó su edad correctamente. Por último, el usuario se guarda en la base de datos y enviamos a la consola que el usuario fue generado y guardado.

¡Pero espera! Antes de poder usar el comando, necesitamos inyectar una instancia de nuestro modelo User

1
    // app/start/artisan.php $user = new User; $artisan->add(new UserGeneratorCommand($user));

2
  

Si tienes una configuración de base de datos y está configurada correctamente, ¡ya deberías poder ejecutar el comando y tener un nuevo usuario guardado en la base de datos!


Comandos de paquetes

Si estás desarrollando un paquete en Laravel, es posible que quieras incluir comandos. El registro de comandos de paquetes es básicamente el mismo proceso, excepto que no puedes agregar el comando en app/start/artisan.php. En su lugar, los resuelves con Artisan desde tu proveedor de servicios de paquetes.

1
    // path/to/your/PackageServiceProvider.php /** * Register the service provider. * * @return void */ public function register() { $this->app['command.package.command'] = $this->app->share(function($app) { return new PackageCommand($app['dependency']); }); $this->commands('command.package.command'); }

2
  

El método commands puede aceptar cualquier número de argumentos y resolverá el comando fuera del contenedor de la aplicación cuando se inicie Artisan.


Conclusión

Cuando compares Artisan en Laravel 4 con su contraparte Laravel 3, descubrirás rápidamente que las mejoras son monumentales. Los comandos ahora se pueden vincular al contenedor de IoC e incluir la inyección de dependencia, proporcionar la salida ANSI en color, usar argumentos y opciones y solicitar la interacción del usuario.

El poder de Artisan, gracias al componente de la consola de Symfony, es increíble. Los comandos van a jugar un papel muy importante a medida que avancemos, ¡así que únete lo antes posible!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.