miércoles, 11 de febrero de 2015

PHP Interfaz de comandos

PHP es conocido y amado como una de las mejores tecnologias para la generacion de sitios web dinamicos. Pero a traves de la linea de comandos de PHP (CLI), tambien puede realizar shell scripting (programacion de linea de comandos) usando su lenguaje favorito PHP. PHP CLI permite ejecutar scripts PHP e incluso fragmentos de codigo PHP fuera del navegador web. En windows, la accion se lleva a cabo dentro de la ventana DOS (tambien conocida como consola o ventana de comandos). En UNIX y Mac OS X, va utilizar una terminal (o un programa similar).

Prueba de su instalacion 

Para comenzar, lo primero que debemos hacer es confirmar que nosotros tenemos PHP CLI disponible, entonces veremos la version.
Con suerte es cuestion de solo seguir unos pasos.

1.- Abra una interfaz de comandos
2.- ponga php -v y pulse la tecla enter o retorno



Si la version de PHP CLI se encuentra instalado en su PATH (Lista de ubicaciones donde el sistema operativo puede encontrar los archivos) con esto deberia ser mas que suficiente.

En el peor de los casos suponiendo que PHP CLI esta instalado, usted tendra que moverse a la ruta de PHP CLI o poner la ruta completa. Junto a la opcion -v, hay otros tres que podemos mostrarle por adelantado:


* -i revela informacion sobre la instalacion de PHP.
* -h accede al archivo de ayuda.
* -m indica los modulos compilados en su instalacion de PHP.

Uso de la CLI

El hecho de que usted pueda realizar script desde la linea de comandos con PHP no significa que siempre deba utilizarlo. En realidad lo que trata PHP es que utilices los conocimientos que ya tienes en PHP en lugar de utilizar algun otro lenguaje de CLI como PERL o shell en los cuales tengas que volver a iniciarte en la sintaxis. PHP CLI nos sirve mucho para realizar tareas basicas tales como:

* Probar fragmentos de codigo PHP rapidamente
* Realizar algun mantenimiento rutinario
* Crear utilidades para el sistema
* Hacer instaladores para sus aplicaciones de PHP

Ejecutando pequeños fragmentos de codigo

Uno de los primeros usos de PHP CLI es probar pequeños fragmentos de codigo rapidamente, sin pasar por el proceso de:

1.- Escribir un script formal de PHP
2.- Colocarlo en un directorio web
3.- Habilitar el servidor web, si no esta ON (activo)
4.- Ejecutar el script PHP en un navegador web

En vez de hacer todo eso, puede probar pequeños fragmentos de codigo con esta sintaxis:

php -r 'codigo_php_aqui'

Para un ejemplo:

php -r "echo 'Hola, mundo!';"

Un par de cosas a tener en cuenta es el uso de comillas dobles o comillas simples (esto dependiendo del sistema operativo donde estes trabajando) y siempre cerrar el codigo usando ; (punto y coma).

Tambien podemos conectar a un servidor remoto usando putty para conectar, solo es necesario ingresar nuestras credenciales.


Para continuar con el ejemplo, vamos a realizar un codigo que nos muestre la ultima modificacion de un archivo, en el cual podemos especificar la ruta completa o movernos al directorio donde se encuentra el archivo.

C:\Users\arthusu>php -r "$filename = 'log.txt'; $fmtime = filemtime($filename);
if(file_exists($filename)){ echo date('F d Y H:i:s',$fmtime); }"
May 02 2014 07:57:30


Mi directorio actual es C:\Users\arthusu en este directorio se encuentra el archivo 'log.txt'.
Y el resultado que nos arroja es May 02 2014 07:57:30 que es la fecha de la ultima modificacion del archivo.

vamos a explicar el codigo, en la variable $filename especificamos la ruta del archivo que queremos saber su ultima modificacion en este caso 'log.txt' pero tu podrias poner la ruta completa, con la variable $fmtime se guarda la ultima fecha de modificacion el archivo 'log.txt' en formato devuelto como tiempo UNIX, por ultimo hacemos un condicional donde verificamos si el archivo existe y si es asi mostramos la ultima fecha de modificacion en el formato anterior usando la funcion date().

Para agregar una nueva linea en consola usamos \n ya que no podemos usar HTML.

C:\Users\arthusu>php -r "echo \"Hola Mundo!\n\";"
Hola Mundo!



PHP CLI interactivo

Desde la version 5.1, PHP es compilado con una extension Readline la cual podemos correr una shell interactiva. Para utilizar PHP CLI Interactivo solo tenemos que seguir los pasos de abajo.

1.- entramos en modo shell interactiva php -a
2.- escribimos un fragmento pequeño de codigo y presionamos la tecla enter





Tambien podemos ver con php -m que el modulo readline esta activado.






Creamos una variable:



Usted puede crear variables, arrays para su posterior consulta, tal como constantes y funciones todo en una sola sesion.

Tambien si ponemos pri y presionamos la tecla TAB nos autocompleta. Gracias a la extension Readline incluimos muchas caracteristicas tales como tambien usar flecha arriba y flecha abajo para ver las lineas anteriores.

Poniendo exit salimos de la sesion del modo shell interactivo.


Creando un script de linea de comandos

Ser capaz de probar pequeños fragmentos de codigo en la linea de comandos es agradable, pero no te llevara lejos. Lo que normalmente se desea hacer es ejecutar scripts (varias lineas) en la linea de comandos. Tales scripts pueden ejecutar algunos archivos, realizar mantenimiento a una base de datos, ejecutar actualizaciones para el sitio web y demas. Un script para utilizarlo en PHP CLI es diferente a un script de PHP WEB.

1.- No se debe utilizar con codigo HTML
2.- No es necesario utilizar la extension .php (aunque si es recomendable)
3.- La primera linea de su script sera:  #!/usr/bin/php

No hay nada de malo en usar codigo HMTL, pero solo va estorbar en el resultado en la consola. En cuanto a la extesion del archivo podria utilizar literalmente cualquier extension o nombre, pero .php todavia es una buena idea. La ultima linea indica para sistemas MAC OS X o UNIX donde se encuentra el ejecutable de php, esta linea es llamada Shebang, en sistemas Windows no es necesario especificarla ya que es ignorada completamente.

Vamos a crear nuestro primer script de linea de comandos y explicarlo.

#!/usr/bin/php
<?php # Script - numero.php
    /* Esta pagina lee un archivo
    * e imprime el numero de lineas junto al contenido.
    * Este script puede ser usado con PHP CLI
    */

    // El archivo:
    $file = 'c:\users\arthusu\log.txt';
    // Imprimimos un mensaje dentro:
    echo "\nNumerando el archivo llamado '$file' ... ----------------\n\n";
    // Leemos en el archivo:
    $data = file($file);
    // Contador del numero de linea:
    $n = 1;
    // Imprimimos para cada linea:
    foreach($data as $line){
        // Imprimimos el numero y linea del archivo:
        echo "$n $line";
        // Incrementamos le numeor de linea:
        $n++;
    } // Terminamos el bucle foreach.
    echo "\n ------------------------ Fin del archivo '$file'.\n";
?>


  
1.- Especificamos la linea Shebang (aunque realmente no es necesaria si estas en windows), y despues abrimos la etique php (porfin!!!)
2.- Indicamos la ruta del archivo a ser numerado en la variable $file
3.-  Usamos la funcion file() para leer el archivo que se guardara en un array
4.- Imprimimos un mensaje de que el archivo comienza
5.- Creamos una variable $n la cual contendra el numero de lineas, recorremos con el bucle foreach() cada linea y aumentamos la variable $n de la linea en 1 para ir contando las lineas.
6.- Terminamos el mensaje de que el archivo termina, y recuerda aqui si cerramos la etiqueta de php.


Usted puede hacer uso de la configuracion php.ini desde la linea de comandos, una manera de buscar el archivo de configuracion es utilizar:

D:\>php -i | find /i "Configuration File"
Configuration File (php.ini) Path => C:\Windows
Loaded Configuration File => C:\xampp\php\php.ini


o tambien:

php --ini
 

Hay algunas opciones con la que podemos cambiar le comportamiento del archivo php.ini.

* -c Le decimos a php donde buscar el archivo php.ini
* -n Le decimos a php que no utilice el archivo php.ini
* -d Establece un valor para php.ini

Por ejemplo, podemos hacer uso de ignore_user_abort en true para que el script se siga ejecutando incluso cuando el usuario aborte el script, para ello cuando invocamos CLI usamos:

php nombredelscript.php -d  ignore_user_abort=1

Corriendo un script de linea de comandos

Hay dos maneras de correr un script en php. La primera manera es utilizar php y el nombre del archivo a ejecutar:

php nombredelscript.php

tambien podemos utilizar la bandera -f:

php -f nombredelscript.php

aunque no es necesario, pero si recomendable.

La segunda manera de hacerlo que se decia es simplemente utilizar el nombre del archivo, pero para ello tienes que tener configurado windows por ejemplo a abrir por defecto ese tipo de archivo con php.exe:

Clic derecho en el archivo > Abrir con... y eliges el archivo php.exe (en mi caso C:\Xampp\htdocs\php\php.exe), para correr el archivo solo entras en la consola y escribes el nombre del archivo, por ejemplo: miarchivo.php y enter.



Podemos utilizar la opcion -l para saber si algun archivo tiene algun error de sintaxis:

php -l elnombredemiarchivo.php

Si no contiene errores devolvera algo como lo siguiente:
No syntax errors detected in xxxx.php


Trabajando con argumentos en la linea de comandos

El ejemplo numero.php es una aplicacion bastante razonable en PHP CLI. El script proporciona un valioso servicio, pero tiene una limitacion: el archivo a ser numerado en el script esta hard-coded. Seria mejor establecer ese valor del archivo cuando se utiliza la aplicacion. Esto puede lograrse facilmente reescribiendo el script para que utilice argumentos en la linea de comandos. Los argumentos en la linea de comandos son valores pasados en una aplicacion cuando se ejecuta. Los argumentos se pasan a la aplicacion invocada añadiendolos despues del nombre de la aplicacion:

nombredelscript.php argumento1 argumento2

En su script PHP puede acceder a estos argumentos refiriendose a $argv y $argc (o mas formal  $_SERVER['argv'] y $_SERVER['argc'])
El array $argv almacena cada argumento proporcionado; $argc almacena el numero de elementos en $argv. El unico incoveniente a la utilizacion de estos es que el nombre del script en si es el primer argumento listado ($_SERVER['argv'][0]):

#!/usr/bin/php
<?php
    echo "\n{$_SERVER['argc']} argumentos recibidos. Los cuales son...\n";
    foreach ($_SERVER['argv'] as $k => $v) {
        echo "$k : $v \n";
    }
?>



 

Vamos a escribir un nuevo script numero.php para que acepte un argumento: el nombre del archivo a numerar.

#!/usr/bin/php
<?php # numero2.php
    /* Esta pagina lee un archivo
    * e imprime el numero de lineas junto al contenido.
    * Este script puede ser usado con PHP CLI
    * Este script espera un argumento (junto al nombre del script)
    * El numbre del archivo a numerar.
    */


    // Verificamos que el nombre fue asignado:
    if ($_SERVER['argc'] == 2){
    // Obtenemos el nombre del archivo
    $file = $_SERVER['argv'][1];

    // Hay que estar seguros que el archivo existe y es un archivo:
    if(file_exists($file) && is_file($file)){
            // Leemos un archivo:
            if($data = file($file)){
                // Imprimimos un mensaje dentro:
                echo "\n Numerando el archivo llamado '$file' \n ---------------------------\n\n";
                // Contador de lineas
                $n = 1;
                // Imprimimos cada linea:
                foreach ($data as $line) {
                    // Imprimimos el numero y la linea:
                    echo "$n $line";
                    // Incrementamos el numero de linea:
                    $n++;
                } // Fin del bucle foreach
                echo "\n ---------------------------\n Fin del archivo '$file'.\n";
                exit(0);
            }else{
                echo "El archivo no pudo ser leido.\n";
                exit(1);
            }
        } else {
            echo "El archivo no existe \n";
            exit(1);
        }
    } else {
        // Imprimimos el uso:
        echo "\n Uso: numero2.php <archivo>\n\n";
        exit(1);
    }
?>




1.- Comenzamos agregando la linea shebang y nuestra etiqueta de apertura php: 
#!/usr/bin/php
<?php

2.- Verificamos que el archivo fue provisto: if ($_SERVER['argc'] == 2){
3.- Estamos seguros de que el archivo existe:

$file = $_SERVER['argv'][1];
if(file_exists($file) && is_file($file)){

El array argv le pusimos 1 por que en 0 esta el nombre del script que estamos ejecutando actualmente y como segundo argumento nuestro argumento que nos interesa.

4.- Leemos el archivo y lo imprimimos:

if($data = file($file)){
                // Imprimimos un mensaje dentro:
                echo "\n Numerando el archivo llamado '$file' \n ---------------------------\n\n";
                // Contador de lineas
                $n = 1;
                // Imprimimos cada linea:
                foreach ($data as $line) {
                    // Imprimimos el numero y la linea:
                    echo "$n $line";
                    // Incrementamos el numero de linea:
                    $n++;
                } // Fin del bucle foreach
                echo "\n ---------------------------\n Fin del archivo '$file'.\n"
;


5.- Devuelve 0 para indicar la correcta ejecucion del script:
exit(0);

Tipicamente 0 representa que se ejecuto sin problemas y un numero distinto significa algun tipo de error. La funcion exit() termina con la ejecucion del script.

6.- Completamos el condicional del paso 4:

}else{
                echo "El archivo no pudo ser leido.\n";
                exit(1);
            }


7.- Completamos el condicional del paso 3:

} else {
            echo "El archivo no existe \n";
            exit(1);
        }


8.- Completamos el condicional del paso 2 y completamos el script:

} else {
        // Imprimimos el uso:
        echo "\n Uso: numero2.php <archivo>\n\n";
        exit(1);
    }


Para ejecutarlo solo usamos: 

php numero2.php <rutaarchivo>

Creacion de una interfaz

El uso de PHP en linea de comandos, se abre todo un nuevo mundo que en la web no tiene: la interfaz de usuario. Claro que la presentacion de una pagina web es algo diferente se utiliza HTML, pero en linea de comandos no es asi, para comenzar la mayoria de la mayoria de los scripts en lineas de comandos indican como se utilizara, si esta se utiliza incorrectamente. Escriba php -varmit y vera lo que quiero decir. El script numero2.php hace esto pero solo poco, los scripts normalmente hacen mas, como mostrar una opcion para ofrecer ayuda, por ejemplo: con el comando -h o --help.
Por ultimo, las aplicaciones de linea de comandos a menudo arrojan un codigo que indica si la operacion se realizo con exito. El numero 0 es devuelto para indicar que no hubo ningun problema, y algunos numeros distintos a cero devuelven distintas cosas. En numero2.php se devuelve 1 para indicar que hay un error. 
Una alternativa para el uso de argumentos de linea de comandos es solicitar la entrada del usuario (si bien se pueden utilizar ambas tecnicas en combinacion). De esta manera puede crear una aplicacion interactiva, donde se pide al usuario informacion y hace algo con lo que se ingresa. 

Tomandos entradas

Por extraño que pueda parecer, teniendo una entrada (input) en la aplicacion de la linea de comandos es exactamente igual que la lectura de datos desde un archivo. Pero en este caso, en lugar de utilizar un manejador de archivo (un puntero a un archivo abierto) vamos a usar una constante especial STDIN. Esto significa entrada estandar (standard input) lo que seria el teclado por defecto. Una forma facil de leer la entrada estandar seria utilizar la funcion fgets():

echo "Dime algo ";
$input = fgets(STDIN);


 
Todo lo escrito alli por el usuario se asigna a $input. Para ser mas precisos con la entrada, me gusta utilizar la funcion  fscanf(). Como printf() y sprintf(). Esta funcion toma el formato de parametros para manejar tipos especificos de datos. Mediante el uso de esta funcion, en lugar de uno mas generico, nos aseguramos de una validacion basica de los datos leidos. En el siguiente ejemplo, fscanf() se utiliza para crear una aplicacion que convierte temperaturas entre grados Fahrenheit y Celsius (y al reves).

#!/usr/bin/php
<?php # temperatura.php

    /* Esta pagina convierte la temperatura entre
    * Fahrenheit y Celsius.
    * Este script es para utilizarlo en PHP CLI.
    * Este script requiere la entrada (input) de un usuario.
    */

    // Entrada del usuario:
    echo "\nIntroduzca la temperatura e indique si es Fahrenheit o Celsius [##.# C/F]: ";

    // Leemos en una entrada condicional:
    if(fscanf(STDIN, '%f %s', $temp_i, $which_i) == 2){
        // Asumimos una salida invalida:
        $which_o = FALSE;

        // Creamos la conversion basado en $wich_i:
        switch (trim($which_i)) {
            // Celsius, convierte a Fahrenheit;
            case 'C':
            case 'c':
                $temp_o = ($temp_i * (9.0/5.0)) + 32;
                $which_o = 'F';
                $which_i = 'C';
                break;
            // Fahrenheit, convierte a Celsius:
            case 'F':
            case 'f':
            $temp_o = ($temp_i - 32) * (5.0/9.0);
            $which_o = 'C';
            $which_i = 'F';
            break;
        } // Fin del SWITCH.

        // Imprimimos los resultados:
        if($which_o){
            printf("%0.1f %s es %0.1f %s.\n", $temp_i, $which_i, $temp_o, $which_o);
        }else{
            echo "Tu fallaste en poner C o F para indicar el tipo de temperatura.\n";
        }
    }else{ // No puso nada en la entrada
        echo "Tu fallastes en usar la sintaxis correcta.\n";
    } // Fin del IF principal.
   
?>



1.- Comenzamos nuestro script temperatura.php:
#!/usr/bin/php
<?php # temperatura.php

2.- Preguntamos al usuario en que quiere convertir la temperatura:
echo "\nIntroduzca la temperatura e indique si es Fahrenheit o Celsius [##.# C/F]: ";
3.- Leemos un numero con punto y una cadena:
if(fscanf(STDIN, '%f %s', $temp_i, $which_i) == 2){
fscanf() intentara leer en, de la entrada estandar, un numero con punto y una cadena. Estos deben coincidir con la temperatura (por ejemplo, 72.3) y el indicador como el tipo de temperatura (C o F). No hay formato 'caracter' en fscanf(), por lo que con %s son para las cadenas. Si puede leer los tipos de datos en ese orden, que van a ser asignados a las variables. La ultima parte de la funcion fscanf() devolvera el numero de valores que asigna a las variables. Asi que si se lee en dos valores, asignado en $temp_i y $which_i, el condicional sabe que los datos adecuados fueron introducidos.
4.- Establecemos una variable en FALSE.
$which_o = FALSE;
Esta variable almacenara las conversiones de la temperatura (la salida).
5.- Realizamos la conversion apropiada:
switch (trim($which_i)) {
            // Celsius, convierte a Fahrenheit;
            case 'C':
            case 'c':
                $temp_o = ($temp_i * (9.0/5.0)) + 32;
                $which_o = 'F';
                $which_i = 'C';
                break;
            // Fahrenheit, convierte a Celsius:
            case 'F':
            case 'f':
            $temp_o = ($temp_i - 32) * (5.0/9.0);
            $which_o = 'C';
            $which_i = 'F';
            break;
        } // Fin del SWITCH.

Si el segundo valor no es un F, C o f, c la conversion no es impresa.
6.- Imprimimos los resultados:
if($which_o){
            printf("%0.1f %s es %0.1f %s.\n", $temp_i, $which_i, $temp_o, $which_o);
        }else{
            echo "Tu fallaste en poner C o F para indicar el tipo de temperatura.\n";
        }


Usamos printf() para manejar el formato del texto.
7.- Completamos el condicional del paso 3 y el script.
}else{ // No puso nada en la entrada
        echo "Tu fallastes en usar la sintaxis correcta.\n";
    } // Fin del IF principal.
   
?>




Nota: Cualquier funcion de archivo de PHP puede ser usada en STDIN. Esto significa que, por ejemplo, usted podria utilizar fgetc() para recuperar un solo caracter o fgetcsv() para recuperar y analizar una linea entera.

Incorporarlo al servidor

Una adicion en la linea de comandos de PHP 5.4 es un servidor web incorporado. Al usarlo, usted puede probar sus scripts PHP en el navegador web sin necesidad de instalar o ejecutar una aplicacion de servidor web como apache. Para ser absolutamente claro, esto no es un servidor web de produccion, pero puede utilizarse para probar scripts PHP rapidamente.

Para utilizar el servidor web incorporado:

1.- Ponga el siguiente comando para saber si tiene disponible la opcion de servidor web:
php -h
La bandera -h nos lleva a la documentacion de ayuda. Si la documentacion incluye la -S (debe ser mayuscula) y la opcion -t, entonces el servidor incorporado esta disponible.



2.- Navegue hasta el directorio que contiene el script PHP que le gustaria probar:

cd /directorio/a/script

Por defecto, el servidor web usara el directorio en el que el servidor comenzo como el directorio raiz, por lo que usted debe navegar hasta alli primero.

3.- Comenzamos el servidor:

php -S 127.0.0.1:8000

Para iniciar el servidor web utilice la opcion -S, seguido por el nombre de host y el puerto a usar. En su propio ordenador localhost es un nombre de host logico y comun. Para el puerto recomendaria, 8000 o 8080, que son alternativas comunes al puerto por defecto de apache 80. Utilizando uno de estos puertos evita posibles conflictos si ya tiene otro servidor web corriendo. Tambien puede utilizar una direccion IP si lo prefieres:

php -S 127.0.0.1:8000


4.- Cargamos http://127.0.0.1:8000/elnombredetuscript.php en tu navegador web. Como se carga la pagina en el navegador web debes utilizar la linea de comandos CLI, te daras cuenta que la ventana de consola o terminal refleja las solicitudes. 


5.- Pulsa ctrl+C en la consola o terminal para detener el servidor web.


Hasta aqui termina este minitutorial espero que les sirva de ayuda, Saludos!

No hay comentarios:

Publicar un comentario en la entrada